/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MIPS;

import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Keiner - jorgue
 */
public class EtapaMEM extends Etapa {

    private Cache datos;
    private int PC = -1;
    private int RA;
    private int RB;
    private int Inm;
    private int RL;
    private int AluOutPut;
    private int[] IR;
    private boolean sigo = true;
    private int PCListo = -2;

    EtapaMEM(pizarra pizarraI, pizarra pizarraD, Semaphore semaphore, Semaphore principal, Cache datos) {
        super(3, pizarraI, pizarraD, semaphore, principal);
        this.datos = datos;
    }

    public void setPCListo(int PC){
        PCListo = PC;
    }
    
    @Override
    public void run() {
        while (true) {
            try {
                organizador.acquire();
                if (izquierda != null) {
                    synchronized (izquierda) {
                        izquierda.lock();
                        if (datos.getRetraso() > 0) {
                            this.setAtrasado(true);
                        } else {
                            this.setAtrasado(false);
                            cambio = izquierda.getCambio();
                            if (cambio == false) {
                                sigo = true;
                            }
                            if (sigo) {
                                PC = izquierda.getPC();
                                IR = izquierda.getIR();
                                RA = izquierda.getRA();
                                RB = izquierda.getRB();
                                RL = izquierda.getRL();
                                Inm = izquierda.getImm();
                                AluOutPut = izquierda.getALU();
                            }
                        }
                        izquierda.setCopiado(true);
                        izquierda.unLock();
                    }
                }

                if (datos.getRetraso() == 0) {
                    if (IR != null && sigo) {
                        //if (PCListo != PC) { //Control para que no entre dos veces a ejecutar la misma instrucción - presenta problemas con los saltos
                            switch (IR[0]) {
                                case 43: //Caso SW
                                    //Resolver Memoria de datos.
                                    datos.guardarDato(RB, AluOutPut);
                                    System.out.println("Guardando en Memoria: " +RB);
                                    break;

                                case 35: //Caso LW
                                    if (datos.getRetraso() == 0) {
                                        AluOutPut = datos.deme(AluOutPut)[0];
                                    } else {
                                        datos.cambioCiclo();
                                    }
                                    break;

                                case 11: //Caso LL
                                    RL = Inm + RA;
                                    AluOutPut = datos.deme(RL)[0];
                                    datos.setRetraso(datos.getRetraso() + 1);
                                    break;

                                case 22: //Caso SC
                                    if (RL == (Inm + RA)) {
                                        datos.guardarDato(RB, Inm + RA);
                                    } else {
                                        RB = 0;
                                    }
                                    break;

                                default: //No accesa a memoria
                            };
                        //}
                    }
                } else {
                    datos.cambioCiclo();
                }

                if (derecha != null) {
                    if (datos.getRetraso() == 0) {
                        esperar = true;
                        while (esperar) {
                            synchronized (derecha) {
                                derecha.lock();
                                if (derecha.getCopiado()) {
                                    esperar = false;
                                    if (PCListo != PC && IR != null) {
                                        derecha.setRA(RA);
                                        derecha.setRB(RB);
                                        derecha.setPC(PC);
                                        derecha.setIR(IR);
                                        derecha.setRL(RL);
                                        derecha.setALU(AluOutPut);
                                        derecha.setCambio(cambio);
                                        PCListo = PC;
                                    }
                                }
                                derecha.unLock();
                            }
                        }
                    }
                    if (cambio) {
                        sigo = false;
                    }
                }
                principal.release();
                //    System.out.println("Saludos desde: " + quienSoy);
            } catch (InterruptedException ex) {
                Logger.getLogger(Etapa.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
